package com.atom.common.activiti;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import com.atom.common.CommonConstant;
import com.atom.common.TaskCompleteType;
import com.atom.common.VariablesConstant;
import com.atom.common.WritedStatus;
import com.atom.common.dao.ProcessDefinitionDao;
import com.atom.common.delegate.TaskCompleteDelegateHandler;
import com.atom.common.entity.base.ProcessDefinitionDO;
import com.atom.common.exception.AvensClaimTaskException;
import com.atom.common.exception.AvensCompleteTaskException;
import com.atom.common.exception.AvensDeleteTaskException;
import com.atom.common.exception.AvensNullPointerException;
import com.atom.common.remote.user.UserUtil;
import com.atom.common.util.GlobalConfigReader;
import com.atom.common.util.JsonUtil;
import com.atom.common.util.PreConditionUtil;

/**
 * Title: ActivitiHandler
 * Description: 对Activiti常用接口的封装
 * @author WEWE
 * @date 2016年9月21日 下午5:35:52
 * @version 1.0
 */
@Component
public class ActivitiHandler {

  private static Logger logger = Logger.getLogger(ActivitiHandler.class);

  /** runtimeService*/
  @Resource
  private RuntimeService runtimeService;
  /** repositoryService*/
  @Resource
  private RepositoryService repositoryService;
  /** identityService*/
  @Resource
  private IdentityService identityService;
  /** taskService*/
  @Resource
  private TaskService taskService;
  /** historyService*/
  @Resource
  private HistoryService historyService;  
  /** 已办任务Handler*/
  @Resource
  private HistoricTaskHandler historicTaskHandler;
  /** 查看已办详细Handler*/
  @Resource
  private HistoricTaskDetailHandler historicTaskDetailHandler;
  /** 待办任务Handler*/
  @Resource
  private RunningTaskHandler runningTaskHandler;
  /** processDefinitionDao*/
  @Resource
  private ProcessDefinitionDao processDefinitionDao;
  /** taskCompleteDelegateHandler*/
  @Resource
  private TaskCompleteDelegateHandler taskCompleteDelegateHandler;

  /**
   * Description: 部署src/main/resources/diagrams下的流程图
   * @param path for example "diagrams/test.bpmn"
   * @return ProcessDefinitionId
   */
  public String deployClasspathResource(String path) {
    PreConditionUtil.checkNotNull(path, "Cannot deploy resource that path is null");

    Deployment deploy = repositoryService.createDeployment().addClasspathResource(path).deploy();
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
    return pd.getId();
  }

  /**
   * Description: 启动流程实例
   * @param processDefinitionId
   * @param variables 参数
   * @return processInstanceId
   */
  public String startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables) {
    PreConditionUtil.checkNotNull(processDefinitionKey, "Cannot start process that processDefinitionKey is null");

    try {
      ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
      return processInstance.getId();
    } catch(Exception e) {
      logger.error("error message = {}" + e.getMessage(), e);
      throw new AvensNullPointerException("ProcessDefinition is null");
    }
  }

  /**
   * Description: 任务认领(加锁)
   * @param taskId
   * @param userId
   */
  public synchronized void claimTask(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "Cannot claim task that taskId is null");
    PreConditionUtil.checkNotNull(userId, "Cannot claim task that userId is null");

    try {
      taskService.claim(taskId, userId);
		runningTaskHandler.lockLocal(taskId, userId);
    } catch (Exception e) {
      logger.error("error message = {}" + e.getMessage(), e);
      throw new AvensClaimTaskException("任务不能加锁(taskId:" + taskId + ")");
    }
  }

  /**
   * Description: 任务反签收(解锁)
   * @param taskId
   */
  public synchronized void unClaimTask(String taskId, String userid) {
    PreConditionUtil.checkNotNull(taskId, "Cannot unclaim task that taskId is null");

    Task task = findTaskByTaskId(taskId);
    if (task.getAssignee() == null) {
      throw new AvensClaimTaskException("任务已经解锁(taskId:" + taskId + ")");
    }

    taskService.claim(taskId, null);
	runningTaskHandler.unLockLocal(taskId, userid);
    return;
  }

  /**
   * Description: 解锁后插入候选人待办
   * @param taskId
   */
  public void insertUnClaimedTask(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "Cannot insert task that taskId is null");

    Task task = findTaskByTaskId(taskId);

    List<IdentityLink> links = taskService.getIdentityLinksForTask(taskId);

    for (IdentityLink identityLink : links) {
      if (StringUtils.equals(IdentityLinkType.CANDIDATE, identityLink.getType())) {
        if (!StringUtils.equals(userId, identityLink.getUserId())) {
          try {
            insertRunning(task, identityLink.getUserId());
          } catch (Exception e) {
            logger.error("error message = {}" + e.getMessage(), e);
          }
        }
      }
    }
  }

  /**
   * Description: 获取最新版本的流程定义列表
   * @return
   */
  public List<ProcessDefinition> getProcessDefinitionList() {
    List<ProcessDefinition> result = repositoryService.createProcessDefinitionQuery().latestVersion().list();
    return result;
  }

  /**
   * Description: 完成任务
   * @param taskId
   */
  public synchronized void completeTask(final String taskId, Map<String, Object> var_cpl) {
    PreConditionUtil.checkNotNull(taskId, "Cannot complete task that taskId is null");

    try {
      Task task = findTaskByTaskId(taskId);
      String pid = (String)var_cpl.get("previousAssignee");
      task.setAssignee(pid);
      Map<String, Object> var_task = findVariablesByTaskId(taskId); 
      logger.info("var_task :" + JsonUtil.ObjectToJsonQuietly(var_task));
      String mainProcessInstanceId = (String) var_task.get(VariablesConstant.MAIN_PROCESS_INSTANCE_ID);
      Map<String, Object> var_process = findVariablesByProcessId(mainProcessInstanceId);
      logger.info("var_process :" + JsonUtil.ObjectToJsonQuietly(var_process));
      var_task.putAll(var_process);
      taskService.complete(taskId, var_cpl);
      // 写入已办表
      historicTaskHandler.insert(task, var_task, TaskCompleteType.MANUAL);
	  // 删除待办数据
	  runningTaskHandler.delete(taskId, task.getAssignee(), var_task);
      // 处理代理日志
      //taskCompleteDelegateHandler.execute(taskId);
    } catch (Exception e) {
      logger.error("error message = {}" + e.getMessage(), e);
      throw new AvensCompleteTaskException("任务完成失败(taskId : "+ taskId +")");
    }
  }
  

  /**
   * Description: 完成部分任务
   * @param taskId
   */
  public synchronized void completeBranchTask(final String taskId, Map<String, Object> var_cpl) {
    PreConditionUtil.checkNotNull(taskId, "Cannot complete task that taskId is null");

    try {
      Task task = findTaskByTaskId(taskId);
      String pid = (String)var_cpl.get("previousAssignee");
      task.setAssignee(pid);
      Map<String, Object> var_task = findVariablesByTaskId(taskId); 
      logger.info("var_task :" + JsonUtil.ObjectToJsonQuietly(var_task));
      String mainProcessInstanceId = (String) var_task.get(VariablesConstant.MAIN_PROCESS_INSTANCE_ID);
      Map<String, Object> var_process = findVariablesByProcessId(mainProcessInstanceId);
      logger.info("var_process :" + JsonUtil.ObjectToJsonQuietly(var_process));
      var_task.putAll(var_process);
      //taskService.complete(taskId, var_cpl);
      // 写入已办表
      historicTaskHandler.insert(task, var_task, TaskCompleteType.MANUAL);
	  // 删除待办数据
	  runningTaskHandler.delete(taskId, task.getAssignee(), var_task);
    } catch (Exception e) {
      logger.error("error message = {}" + e.getMessage(), e);
      throw new AvensCompleteTaskException("任务完成失败(taskId : "+ taskId +")");
    }
  }

  /**
   * Description: 写入待办
   * @param task
   * @param userId
   */
  public void insertRunning(Task task, String userId) {
    PreConditionUtil.checkNotNull(task, "Cannot insert remote running that task is null");
    PreConditionUtil.checkNotNull(userId, "Cannot insert remote running that userId is null");

    Map<String, Object> variables = new HashMap<String, Object>();
    // TASK SCOPE VARS
    Map<String, Object> var_task = taskService.getVariables(task.getId());
    String mainProcessInstanceId = (String) var_task.get(VariablesConstant.MAIN_PROCESS_INSTANCE_ID);
    // EXECUTION SCOPE VARS
    Map<String, Object> var_process = runtimeService.getVariables(mainProcessInstanceId);
    variables.putAll(var_process);
    variables.putAll(var_task);
    runningTaskHandler.insert(task, variables, userId);
  }

  /**
   * Description: 删除任务
   * @param taskId
   */
  public void deleteProcess(String processInstanceId, final String taskId) {
    PreConditionUtil.checkNotNull(processInstanceId, "Cannot delete process that processInstanceId is null");
    PreConditionUtil.checkNotNull(taskId, "Cannot delete process that taskId is null");

    try {
      Task task = findTaskByTaskId(taskId);
      Map<String, Object> var_task = findVariablesByTaskId(taskId);
      runtimeService.deleteProcessInstance(processInstanceId, "");
      // 写入已办表
      historicTaskHandler.insert(task, var_task, TaskCompleteType.MANUAL);
      // 删除待办数据
      runningTaskHandler.delete(taskId, task.getAssignee(), var_task);
    } catch (Exception e) {
      logger.error("error message = {}" + e.getMessage(), e);
      throw new AvensDeleteTaskException("任务删除失败(taskId : "+ taskId +")");
    }
  }

  /**
   * Description: 根据taskId查找任务
   * @param taskId
   * @return
   */
  public Task findTaskByTaskId(String taskId) {
    PreConditionUtil.checkNotNull(taskId, "Cannot find task that taskId is null");

    return taskService.createTaskQuery().taskId(taskId).singleResult();
  }

  /**
   * Description: 根据流程实例Id和任务定义Key查找任务
   * @param processInstanceId
   * @param taskDefinitionKey
   * @return
   */
  public Task findTaskByProcessIdByTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) {
    PreConditionUtil.checkNotNull(processInstanceId, "Cannot find task that processInstanceId is null");
    PreConditionUtil.checkNotNull(taskDefinitionKey, "Cannot find task that taskDefinitionKey is null");

    return taskService.createTaskQuery().processInstanceId(processInstanceId).taskDefinitionKey(taskDefinitionKey).singleResult();
  }

  /**
   * Description: 根据流程实例Id和任务定义Key查找任务列表
   * @param processInstanceId
   * @param taskDefinitionKey
   * @return
   */
  public List<Task> findTaskListByProcessIdByTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) {
    PreConditionUtil.checkNotNull(processInstanceId, "Cannot find tasks that processInstanceId is null");
    PreConditionUtil.checkNotNull(taskDefinitionKey, "Cannot find tasks that taskDefinitionKey is null");

    return taskService.createTaskQuery().processInstanceId(processInstanceId).taskDefinitionKey(taskDefinitionKey).list();
  }

  /**
   * Description: 根据参数主流程id与任务定义查找任务
   * @param mainProcessInstanceId
   * @param taskDefinitionKey
   * @return
   */
  public List<Task> findTaskByMainProcessInstanceIdByDefinitionKey(String mainProcessInstanceId,
      String taskDefinitionKey) {
    PreConditionUtil.checkNotNull(mainProcessInstanceId, "Cannot find task that mainProcessInstanceId is null");
    PreConditionUtil.checkNotNull(taskDefinitionKey, "Cannot find task that taskDefinitionKey is null");

    return taskService.createTaskQuery()
        .taskDefinitionKey(taskDefinitionKey)
        .processVariableValueEquals(VariablesConstant.MAIN_PROCESS_INSTANCE_ID, mainProcessInstanceId)
        .list();    
  }

  /**
   * Description: 根据受理人查找待办任务列表
   * @param userId
   * @return
   */
  public List<Task> findTaskListByAssignee(String userId) {
    PreConditionUtil.checkNotNull(userId, "Cannot find task that userId is null");

    return taskService.createTaskQuery().taskAssignee(userId).list();
  }

  /**
   * Description: 根据候选人查找待办任务列表
   * @param userId
   * @return
   */
  public List<Task> findTaskListByCandidateUser(String userId) {
    PreConditionUtil.checkNotNull(userId, "Cannot find task that userId is null");

    return taskService.createTaskQuery().taskCandidateUser(userId).list();
  }

  /**
   * Description: 同时查找任务受理人和任务候选人的任务列表
   * @param userId
   * @return
   */
  public List<Task> findTaskListByUser(String userId) {
    PreConditionUtil.checkNotNull(userId, "Cannot find task that userId is null");

    return taskService.createTaskQuery().taskCandidateOrAssigned(userId).orderByTaskCreateTime().desc().list();
  }

  /**
   * Description: 根据taskId和key查找参数
   * @param taskId
   * @param key
   * @return
   */
  public Object findVariableByTaskIdByKey(String taskId, String key) {
    PreConditionUtil.checkNotNull(taskId, "Cannot find variable that taskId is null");
    PreConditionUtil.checkNotNull(key, "Cannot find variable that key is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    return taskService.getVariable(taskId, key);
  }

  /**
   * Description: 根据taskId和key查找历史参数
   * @param taskId
   * @param key
   * @return
   */
  public Object findHistoryVariableByTaskIdByKey(String taskId, String key) {
    PreConditionUtil.checkNotNull(taskId, "Cannot find variable that taskId is null");
    PreConditionUtil.checkNotNull(key, "Cannot find variable that key is null");

    HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();

    if (task == null) {
      throw new AvensNullPointerException("HistoricTaskInstance is null where taskId = " + taskId);
    }

    String processId = task.getProcessInstanceId();
    HistoricVariableInstance variable = historyService.createHistoricVariableInstanceQuery().excludeTaskVariables().processInstanceId(processId).variableName(key).singleResult();
    return variable != null ? variable.getValue() : null;
  }

  /**
   * Description: 根据taskId查找参数
   * @param taskId
   * @return
   */
  public Map<String, Object> findVariablesByTaskId(String taskId) {
    PreConditionUtil.checkNotNull(taskId, "Cannot find variables that taskId is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    return taskService.getVariables(taskId);
  }

  public Map<String, Object> findVariablesByProcessId(String processInstanceId) {
    PreConditionUtil.checkNotNull(processInstanceId, "Cannot find variables that processInstanceId is null");

    return runtimeService.getVariables(processInstanceId);
  }

  /**
   * Description: 查询流程参数
   * @param mainProcessInstanceId
   * @param key
   * @return
   */
  public Object findVariableByProcessIdByKey(String mainProcessInstanceId, String key) {
    PreConditionUtil.checkNotNull(mainProcessInstanceId, "Cannot find variable that processInstanceId is null");
    PreConditionUtil.checkNotNull(key, "Cannot find variable that key is null");

    return runtimeService.getVariable(mainProcessInstanceId, key);
  }

  /**
   * Description: 
   * @param taskId
   * @return
   */
  public String findSuperProcessInstanceId(String taskId) {    
    PreConditionUtil.checkNotNull(taskId, "Cannot find superProcessInstanceId that taskId is null");

    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    String subProcessInstanceId = task.getProcessInstanceId();
    return runtimeService.createProcessInstanceQuery().subProcessInstanceId(subProcessInstanceId).singleResult().getProcessInstanceId();
  }

  /**
   * Description: 流程多个参数覆值
   * @param taskId
   * @param variables
   */
  public void setVariablesByTaskId(String taskId, Map<String, Object> variables) {
    PreConditionUtil.checkNotNull(taskId, "Cannot set variables that taskId is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    taskService.setVariables(taskId, variables);
  }

  /**
   * Description: 任务多个参数覆值
   * @param taskId
   * @param variables
   */
  public void setVariablesLocalByTaskId(String taskId, Map<String, Object> variables) {
    PreConditionUtil.checkNotNull(taskId, "Cannot set variables that taskId is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    taskService.setVariablesLocal(taskId, variables);
  }

  /**
   * Description: 流程单个参数覆值
   * @param taskId
   * @param key
   * @param value
   */
  public void setVariableByTaskId(String taskId, String key, Object value) {
    PreConditionUtil.checkNotNull(taskId, "Cannot set variable that taskId is null");
    PreConditionUtil.checkNotNull(key, "Cannot set variable that key is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    taskService.setVariable(taskId, key, value);
  }

  /**
   * Description: 流程参数赋值
   * @param processInstanceId
   * @param key
   * @param value
   */
  public void setProcessVariable(String processInstanceId, String key, Object value) {
    PreConditionUtil.checkNotNull(processInstanceId, "Cannot set variable that processInstanceId is null");
    PreConditionUtil.checkNotNull(key, "Cannot set variable that key is null");

    runtimeService.setVariable(processInstanceId, key, value);
  }

  /**
   * Description: 任务单个参数覆值
   * @param taskId
   * @param key
   * @param value
   */
  public void setVariableLocalByTaskId(String taskId, String key, Object value) {
    PreConditionUtil.checkNotNull(taskId, "Cannot set variable that taskId is null");
    PreConditionUtil.checkNotNull(key, "Cannot set variable that key is null");

    if (taskService.createTaskQuery().taskId(taskId).singleResult() == null) {
      throw new AvensNullPointerException("task is null where taskId = " + taskId);
    }

    taskService.setVariableLocal(taskId, key, value);
  }

  /**
   * Description: 初始化流程参数
   * @param processDefKey
   * @param processInstanceId
   * @param user
   * @param processInstanceName
   * @param priorityId
   */
  public void initProcessVariables(String processDefKey, String processInstanceId, 
      UserUtil user, String processInstanceName, String priorityId) {
    PreConditionUtil.checkNotNull(processDefKey, "processDefKey is null");
    PreConditionUtil.checkNotNull(processInstanceId, "processInstanceId is null");

    List<ProcessDefinitionDO> processList = processDefinitionDao.findByProperty("processDefinitionKey", processDefKey);
    if (processList == null) {
      throw new AvensNullPointerException("process definition list is null where key = " + processDefKey);
    }

    ProcessDefinitionDO def = processList.get(0);
    // 记录流程变量
    setProcessVariable(processInstanceId, VariablesConstant.MAIN_PROCESS_INSTANCE_ID, 
        processInstanceId);
    setProcessVariable(processInstanceId, VariablesConstant.PROCESS_CREATOR, 
        PreConditionUtil.checkNotNull(user.getUserid(), "userid is null"));
    //setProcessVariable(processInstanceId, VariablesConstant.PROCESS_CREATOR_DEPART, 
    //    PreConditionUtil.checkNotNull(user.getOrgid(), "orgid is null"));
    setProcessVariable(processInstanceId, VariablesConstant.PROCESS_INSTANCE_NAME, 
        processInstanceName);
    setProcessVariable(processInstanceId, VariablesConstant.PROCESS_DEFINITION_NAME, 
        PreConditionUtil.checkNotNull(def.getProcessDefinitionName(), "processDefinitionName is null"));
    setProcessVariable(processInstanceId, VariablesConstant.SYSTEM_MODULER, 
        PreConditionUtil.checkNotNull(def.getSystemModuler(), "systemModuler is null"));
    setProcessVariable(processInstanceId, VariablesConstant.PROCESS_NUMBER, 
        PreConditionUtil.checkNotNull(def.getProcessNumber(), "processNumber is null"));
    setProcessVariable(processInstanceId, VariablesConstant.PRIORITY, 
        priorityId == null ? "50" : priorityId);
    setProcessVariable(processInstanceId, VariablesConstant.PROCESS_DEFINITION_KEY, 
        processDefKey);
    // 初始化流程参数
    setProcessVariable(processInstanceId, VariablesConstant.IS_REJECT, false);
    setProcessVariable(processInstanceId, VariablesConstant.PREVIOUS_ASSIGNEE, null);
    setProcessVariable(processInstanceId, VariablesConstant.WRITED, WritedStatus.UNDO);
  }

  /**
   * Description: 将新建的任务写入待办表，如果WritedStatus=UNDO表示没有写过，
   * 写完待办表后把WritedStatus置为DONE
   * @param taskId
   * @param processInstanceId
   * @param user
   */
  public void createRemoteRunning(String taskId, String processInstanceId, UserUtil user) {
    if (WritedStatus.UNDO == 
        (Integer)findVariableByTaskIdByKey(taskId, VariablesConstant.WRITED)) {
      //获取申请任务
      Task task = findTaskByTaskId(taskId);  
      //写入待办表
      insertRunning(task, user.getUserid()); 
      setProcessVariable(processInstanceId, VariablesConstant.WRITED, WritedStatus.DONE);
    }
  }

  public boolean ProcDefKeyIsExist(String procDefKey) {
    Long count = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).count();
    return count == 0 ? false : true;
  }

  /**
   * Description: 更新流程实例名称，并更新平台待办表里的任务名称
   * @param processInstanceId
   * @param biaoTi
   */
  public void updateProcessInstanceName(String taskId, String processInstanceId, String name) {
    String taskName = (String) findVariableByProcessIdByKey(processInstanceId, VariablesConstant.PROCESS_INSTANCE_NAME);
    if (!StringUtils.equals(name, taskName)) {
      setProcessVariable(processInstanceId, VariablesConstant.PROCESS_INSTANCE_NAME, name);
      if (WritedStatus.DONE == 
          (Integer)findVariableByProcessIdByKey(processInstanceId, VariablesConstant.WRITED)) {
        runningTaskHandler.updateTaskName(taskId, name);
      }
    }

  }

  
  /**
   * Description: 根据公文类型和用户ID查找任务，代理用
   * @param userId
   * @param processDefKey
   * @return
   */
  public List<Task> findTaskListByUserByProcessDefKey(String userId, String processDefKey) {
    PreConditionUtil.checkNotNull(userId, "UserId is null");
    return taskService.createTaskQuery().processVariableValueEquals(VariablesConstant.PROCESS_DEFINITION_KEY, processDefKey).taskCandidateOrAssigned(userId).orderByTaskCreateTime().desc().list();
  }

  /**
   * Description: 任务添加候选人，代理用
   * @param taskId
   * @param userId
   */
  public void addCandidate(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");
    PreConditionUtil.checkNotNull(userId, "UserId is null");

    taskService.addCandidateUser(taskId, userId);
  }

  public void removeCandidate(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");
    PreConditionUtil.checkNotNull(userId, "UserId is null");

    taskService.deleteCandidateUser(taskId, userId);
  }

  public List<String> listTaskUsers(String taskId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");

    List<IdentityLink> ll = taskService.getIdentityLinksForTask(taskId);
    List<String> users = new ArrayList<String>();
    for (IdentityLink l : ll) {
      users.add(l.getUserId() + l.getType());
    }
    return users;
  }

  /**
   * Description: 替换任务候选人，代理用
   * @param taskId
   * @param owner
   * @param userId
   */
  public void updateCandidate(String taskId, String owner, String userId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");
    PreConditionUtil.checkNotNull(userId, "UserId is null");
    PreConditionUtil.checkNotNull(userId, "owner is null");


    taskService.addCandidateUser(taskId, userId);
    taskService.deleteCandidateUser(taskId, owner);
  }

  /**
   * Description: 替换任务受理人，代理用
   * @param taskId
   * @param userId
   */
  public void updateAssignee(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");
    PreConditionUtil.checkNotNull(userId, "UserId is null");

    taskService.claim(taskId, null);
    taskService.claim(taskId, userId);

  }

  public boolean taskHasUser(String taskId, String userId) {
    PreConditionUtil.checkNotNull(taskId, "TaskId is null");
    PreConditionUtil.checkNotNull(userId, "UserId is null");

    Task task = taskService.createTaskQuery().taskId(taskId).taskCandidateOrAssigned(userId).singleResult();
    if (task != null) {
      logger.info(taskId + " task has user true" + userId);
      return true;
    } else {
      logger.info(taskId + " task has user false" + userId);
      return false;
    }
  }


}
